
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

#include "soc.h"
#include "dbg_cli.h"
#include "upaket.h"
#include "dw_i2c.h"
#include "fatfs.h"
#include "fatfs.c"
// #include  "case_iic.c"


/*
    debug bridge spi 是个 6 pin 接口,  cs, clk, dat[3:0];
    在 milkv-duo 开发板上, 选择 SPI-NOR-NAND 对应的 6 pin 接口;
   
    PAD     XGPIOA    SPI-NOR      milkv-duo
    17      26        HOLD#        GP21
    18      22        SCK          GP18
    19      25        MOSI         GP19
    20      27        WP#          GP20
    21      23        MISO         GP16
    22      24        CS#          GP17

    
    对于芯片的 PAD MUX 和 PAD control 的寄存器是按照 PAD 位置来定义.
*/

void qspi_pad_config( void )
// 配置QSPI接口的引脚功能。根据条件编译选择不同的引脚复用配置。
{
 
#if 0	
 
 /* GPIO */
 write_reg( PAD_MUX_17, 3 );
 write_reg( PAD_MUX_18, 3 );
 write_reg( PAD_MUX_19, 3 );
 write_reg( PAD_MUX_20, 3 );
 write_reg( PAD_MUX_21, 3 );
 write_reg( PAD_MUX_22, 3 );
#else
 
 /* SPI-NOR, */
 write_reg( PAD_MUX_17, 1 );
 write_reg( PAD_MUX_18, 1 );
 write_reg( PAD_MUX_19, 1 );
 write_reg( PAD_MUX_20, 1 );
 write_reg( PAD_MUX_21, 1 );
 write_reg( PAD_MUX_22, 1 );
//  IIC
 write_reg( PAD_MUX_23, 4 );
 write_reg( PAD_MUX_24, 4 );


write_reg(PAD_MUX_14,3);




/*
切换 4 个信号, ephy TXP, TXN, RXP, RXN : 
配置 ephy 放弃控制权,  让数字部分逻辑来控制这 4 个信号线.
*/
uintptr_t ephy = 0x3009000;

		/**/
write_reg( ephy + 0x804, 0x1 );
write_reg( ephy + 0x808, 0x101 );
write_reg( ephy + 0x800, 0x905 );

		/* wait 10us */
test_sleep( 100 );

		/**/
write_reg( ephy + 0x7C, 0x051F );
write_reg( ephy + 0x78, 0x0F00 );
write_reg( ephy + 0x74, 0x0606 );
write_reg( ephy + 0x70, 0x0606 );




write_reg(0x030010c0,6);
write_reg(0x030010c4,6);
write_reg(0x030010c8,6);
write_reg(0x030010cc,3);





#endif
 
  
 // [11] 输出电平转换速率限制. 0=无效(较快) ; 1=有效(较慢)
 // [8] 输入施密特触发强度?
 // [7:5] 输出驱动能力.
    // [3] 下拉电阻, 0=无效; 1=有效
    // [2] 上拉电阻, 0=无效; 1=有效
 
 // PAD_CTL_17
 // PAD_CTL_18
 // PAD_CTL_19
 // PAD_CTL_20
 // PAD_CTL_21
 // PAD_CTL_22
}




uint32_t test_write_fifo( cvi_spinor_regs_t * psnor, uint32_t value )
{
	uint32_t ffss;
	
	/**/
	while ( true )  {
		ffss = psnor->FIFO_PT;
		if ( (ffss & 0xF) <= 4 )  {
			break;
		}
	}

	psnor->FF32 = value;
	ffss = psnor->FIFO_PT;
	ffss = (ffss << 16)  | psnor->INT_STS;
	return ffss;
}


int test_read( cvi_spinor_regs_t * psnor, uint16_t addr, int tcnt, uint32_t * pdat )
{
	uint32_t temp;
	uint32_t ffss;
	uint32_t ints;
	uint32_t tagh;
	int offs;
	
	if ( tcnt <= 1 )  {
		tcnt = 1;
	}

	// 1 : Read
	tagh = 0x10000 | addr;
	tagh = ( tagh << 7 ) | ( (tcnt - 1) & 0x7F );

	/* clear irqs and fifo */
	psnor->FIFO_PT = 0;
	psnor->CE_CTRL = 0;
	psnor->INT_STS = 0;

	/* trans multi words */
	psnor->TRAN_NUM = tcnt << 2;

	/* RX, addr(3) ,  ff_trg_lvl = 4bytes */
	temp = 0x2301;
	psnor->TRAN_CSR = temp;

	/* push addr : 24 bits */
	psnor->FF32 = __builtin_bswap32( tagh );
	ffss = psnor->FF8;

	psnor->TRAN_CSR = temp | 0x8000;
	
	/* check RD fifo int */
	while ( true )  {

		ints = psnor->INT_STS;
		psnor->INT_STS = 0;

		if ( ints & 0x4 )  {
			break;
		}
	}

	offs = 0;
	while ( true )  {

		ffss = psnor->FIFO_PT;
		if ( (ffss & 0xF) >= 4 )  {
			pdat[offs] = psnor->FF32;
			offs += 1;
		}

		ints = psnor->INT_STS;

		if ( ints & 0x1 )  {
			break;
		}
	}

	printf( "offs = %d\n", offs );
	return 0;
}


/*
tcnt : 表示后面 pdat 数组的长度, <=0 都没有意义.  最大值 128.
*/
int test_write( cvi_spinor_regs_t * psnor, uint16_t addr, int tcnt, uint32_t * pdat )
{
	uint32_t temp;
	uint32_t ffss;
	uint32_t ints;	
	volatile uint32_t tagh;
	int offs;

	if ( (tcnt < 1) || (tcnt > 128) )  {
		return 123;
	}

	// 0 : Write
	tagh = addr;
	tagh = ( tagh << 7 ) | ( (tcnt - 1) & 0x7F );

	/* clear irqs and fifo */
	psnor->FIFO_PT = 0;
	psnor->CE_CTRL = 0;
	psnor->INT_STS = 0;

	/* trans multi words */
	psnor->TRAN_NUM = tcnt << 2;

	/* RX, cmd + addr(2) ,  ff_trg_lvl = 4bytes */
	temp = 0x2302;
	psnor->TRAN_CSR = temp;

	/* push addr : 24 bits */
	psnor->FF32 = __builtin_bswap32( tagh );
	ffss = psnor->FF8;
	
	/**/
	psnor->TRAN_CSR = temp | 0x8000;

	/* check WR fifo int */
	while ( true )  {

		ints = psnor->INT_STS;
		psnor->INT_STS = 0;

		if ( ints & 0x8 )  {
			break;
		}
	}

	/* push all data */
	offs = 0;
	while ( true )  {

		ffss = psnor->FIFO_PT;
		if ( (ffss & 0xF) <= 4 )  {
			psnor->FF32 = pdat[offs];
			offs += 1;
		}

		if ( offs == tcnt ) {
			break;
		}
	}

	/* wait complete */
	while ( true )  {
		ints = psnor->INT_STS;

		if ( ints & 0x1 )  {
			break;
		}
	}

	return 0;
}


int bl2_dbg_noread( void * pctx, int argc, const char * argv[] )
{
	int iret;
	uint32_t temp;
	uint16_t addr;
	uint32_t tary[200];
	cvi_spinor_regs_t * psnor = (cvi_spinor_regs_t *)SPINOR_BASE;
	

	if ( argc < 3 )  {
		goto usage;
	}

	iret = debug_str2uint( argv[1], &temp );
	if ( iret != 0 )  {
		printf( "addr fmt error %d\n", iret );
		goto usage;
	}

	if ( temp > 0xFFFC )  {
		printf( "addr range error \n" );
		goto usage;
	}

	addr = (uint16_t)temp;

	iret = debug_str2uint( argv[2], &temp );
	if ( iret != 0 )  {
		printf( "addr fmt error %d\n", iret );
		goto usage;
	}

	if ( temp > 128 )  {
		printf( "cntw range error \n" );
		goto usage;
	}

	iret = test_read( psnor, addr, (int)temp, tary );
	printf( "iret = %d\n", iret );
	return 0;

usage:
	printf( "%s <addr> <cntw>\n", argv[0] );
	return 0;
}



int bl2_dbg_norwrite( void * pctx, int argc, const char * argv[] )
{
	int iret;
	uint32_t temp;
	uint16_t addr;
	uint32_t tary[20];
	cvi_spinor_regs_t * psnor = (cvi_spinor_regs_t *)SPINOR_BASE;

	if ( argc < 3 )  {
		goto usage;
	}

	iret = debug_str2uint( argv[1], &temp );
	if ( iret != 0 )  {
		printf( "addr fmt error %d\n", iret );
		goto usage;
	}

	if ( temp > 0xFFFC )  {
		printf( "addr range error \n" );
		goto usage;
	}

	addr = (uint16_t)temp;

	for ( int i=2; i<argc; i++ )  {
		iret = debug_str2uint( argv[i], &tary[i-2] );
		if ( iret != 0 )  {
			printf( "data[%d] fmt error %d\n", i-2, iret );
			goto usage;
		}
	}

	iret = test_write( psnor, addr, argc-2, tary );
	printf( "write ret = %d\n", iret );
	return 0;

usage:
	printf( "%s <addr> [data1] [data2] ...\n", argv[0] );
	return 0;
}



/*
fifo 最大深度 8 bytes.
会根据 write 操作的的 mask 来 push 数据.
如果 word 写操作, 那么 push 4 bytes.
但是 byte 写操作, 只会 push 1 byte.

怀疑, 硬件不认识 half (uint16) 写操作.
*/

int bl2_dbg_nor( void * pctx, int argc, const char * argv[] )
{
	cvi_spinor_regs_t * psnor = (cvi_spinor_regs_t *)SPINOR_BASE;

	/* default setting .*/
	psnor->DMMR_CTRL = 0;			/* disable */
	psnor->SPI_CTRL = 0x8000F;		/* div = 2 *( 0xF + 1) = 32 */
	psnor->INT_STS = 0;
	psnor->FIFO_PT = 0;				/* clear fifo */
	psnor->CE_CTRL = 0;

	return 0;
}


typedef struct {
    __IOM uint32_t    CTRLR0; //0x000 Control Register 0
    __IOM uint32_t    CTRLR1; //0x004 Control Register 1
    __IOM uint32_t    SPIENR; //0x008 SPI Enable Register
    __IOM uint32_t    MWCR; //0x00c Microwire Control Register
    __IOM uint32_t    SER; //0x010 Slave Enable Register
    __IOM uint32_t    BAUDR; //0x014 Baud Rate Select
    __IOM uint32_t    TXFTLR; //0x018 Transmit FIFO Threshold Level
    __IOM uint32_t    RXFTLR; //0x01c Receive FIFO Threshold Level
    __IOM uint32_t    TXFLR; //0x020 Transmit FIFO Level Register
    __IOM uint32_t    RXFLR; //0x024 Receive FIFO Level Register
    __IOM uint32_t    SR; //0x028 Status Register
    __IOM uint32_t    IMR; //0x02c Interrupt Mask Register
    __IOM uint32_t    ISR; //0x030 Interrupt Status Register
    __IOM uint32_t    RISR; //0x034 Raw Interrupt Status Register
    __IOM uint32_t    TXOICR; //0x038 Transmit FIFO Overflow Interrupt Clear Register
    __IOM uint32_t    RXOICR; //0x03c Receive FIFO Overflow Interrupt Clear Register
    __IOM uint32_t    RXUICR; //0x040 Receive FIFO Underflow Interrupt Clear Register
    __IOM uint32_t    MSTICR; //0x044 Multi-Master Interrupt Clear Register
    __IOM uint32_t    ICR; //0x048 Interrupt Clear Register
    __IOM uint32_t    DMACR; //0x04c DMA Control Register
    __IOM uint32_t    DMATDLR; //0x050 DMA Transmit Data Level
    __IOM uint32_t    DMARDLR; //0x054 DMA Receive Data Level
    __IOM uint32_t    IDR; //0x058 Identification Register
    __IOM uint32_t    SSI_VERSION_ID; //0x05c SS Interrupt Enable Register
    __IOM uint32_t    DR[36]; //0x060 Data Register
    __IOM uint32_t    RX_SAMPLE_DLY; //0x0f0 Rx Sample Delay Register
}spi_regs_t;
// SPI 控制寄存器设置
#define SPI_CTRL0_CPOL     (1 << 7) // 时钟极性 (高电平有效)

/*
  47(SDO-OUT), 48(SDI ), 49(SCK), 50(CS-PROGRAM_B)
*/
#define GPIO_PIN_15 (1 << 15)
#define GPIO_PIN_26 (1 << 26)
int SPI_WRITE_DATA(uint8_t *buffer, uint32_t tsiz){

    spi_regs_t *pport = (spi_regs_t *)0x04190000;
    cvi_port_regs_t *gpio= (cvi_port_regs_t *)CVI_GPIOA_BASE;
    cvi_port_regs_t *gpio_b= (cvi_port_regs_t *)CVI_GPIOB_BASE;

    gpio_b->OPE |=GPIO_PIN_26; // 设置 GPIO26 为输出模式
    gpio_b->OUT |=GPIO_PIN_26; // 设置 GPIO26 输出高电平
    // 设置 GPIO15 输出高电平
    gpio->OUT|= GPIO_PIN_15;
    // 设置 GPIO15 为输出模式
    gpio->OPE |= GPIO_PIN_15;
   
     // 配置 SPI 控制寄存器
    pport->SPIENR = 0;  // 关闭 SPI
    pport->CTRLR0 = 0x7; // CPOL=1 , 时钟极性为高电平有效, 8位数据
    pport->BAUDR = 0x0000000C; // 100KHz
    pport->MWCR= 0x2;//SSI transfer mode

    pport->SPIENR = 1;  // 使能 SPI

    
    gpio_b->OUT &= ~GPIO_PIN_26; // 设置 GPIO26 输出低电平
    test_sleep(50);//100==500ns
    gpio_b->OUT |=GPIO_PIN_26; // 设置 GPIO26 输出高电平
    test_sleep(200);//100==500ns
    pport->SER = 0x1; // 使能 SPI 设备


for (uint32_t i = 0; i < tsiz; i++) {
    pport->DR[0] = buffer[i]; // 写数据到 DR 寄存器
    while ((pport->SR & 0x2) ==0) {} // 等待传输完成
}
for (uint32_t i = 0; i < 5; i++)
{
    pport->DR[0] = 0xFF; // 写数据到 DR 寄存器
    while ((pport->SR & 0x2) ==0) {} // 等待传输完成
}

    printf("write done..\n");
    uint32_t status=pport->SR;
    printf("status = %08x\n", status);
    // // 读取接收数据
    // for(int i=0;i<6;i++){
    //      uint32_t received_data = pport->DR[0];
    //      printf("received_data = %08x\n", received_data);
    // }


    return 0;

}


int bl2_dbg_spi(void *pctx, int argc, const char *argv[])
{
    int iret;
    uint32_t temp;
    uint32_t tsiz;
    fatfs_t fsinfo;
    spi_regs_t *pport = (spi_regs_t *)0x04190000;
    cvi_port_regs_t *gpio= (cvi_port_regs_t *)CVI_GPIOA_BASE;

      // 分配 6MB 的内存
    uint8_t *buffer = (uint8_t *)malloc(6 * 1024 * 1024);
    if (buffer == NULL) {
        printf("Memory allocation failed\n");
        return 4; // 返回一个错误码
    }

    if ( argc < 2 )  {
		goto usage;
	}
    iret = fatfs_init( &fsinfo );
	if ( iret != 0 )  {
		printf( "fatfs info fail, %d\n", iret );
		return 1;
	}
    iret = fatfs_fstat( &fsinfo, argv[1], &tsiz );
	if ( iret != 0 )  {
		printf( "fstat iret = %d\n", iret );
		return 2;
	}
    printf( "fstat ok, size=%u\n", tsiz );
	if ( tsiz <= 0 )  {
		return 3;
	}
    iret = fatfs_fread( &fsinfo, argv[1], buffer );
	if ( iret <= 0 )  {
		printf( "fread iret = %d\n", iret );
		return 3;
	}

	
    printf("read succ..\n");


    SPI_WRITE_DATA(buffer, tsiz);

    // 释放内存
    free(buffer);
     
    return 0;
usage:
	printf( "usage:\n" );
	printf( "\t%s <fname> \n", argv[0] );
	return 0;    
}


////
void dw_iic_init( dw_iic_regs_t * piic, uint32_t baud )
{
    uint32_t bhz;
    uint32_t period;
    uint32_t lcnt; // oof this one hurts
    uint32_t hcnt;
    uint32_t sda_tx_hold_count;
    uint32_t spklen;
    uint32_t temp;
    
    /**/
    dw_iic_disable( piic );
    
    /**/
    // bhz = drv_get_apb_freq();
    bhz = 25000000; // TODO: get apb freq from soc.h
    period = (bhz + baud / 2) / baud;
    lcnt = period * 3 / 5; // oof this one hurts
    hcnt = period - lcnt;
    spklen = lcnt < 16 ? 1 : lcnt / 16;
    
    piic->IC_FS_SCL_HCNT = hcnt;
    piic->IC_FS_SCL_LCNT = lcnt;
    piic->IC_FS_SPKLEN = spklen;
    
    /**/
    sda_tx_hold_count = ((bhz * 3) / 10000000) + 1;
    temp = piic->IC_SDA_HOLD;
    temp = (temp & 0xFFFF0000) | sda_tx_hold_count;
    piic->IC_SDA_HOLD = temp;
    
    /**/
    return;
}

void dw_iic_set_master_mode(dw_iic_regs_t *iic_base)
{
    uint32_t iic_status;
    iic_status = dw_iic_get_iic_status(iic_base);
    dw_iic_disable(iic_base);
    uint32_t val = DW_IIC_CON_MASTER_EN | DW_IIC_CON_SLAVE_EN; ///< set 1 to enabled master mode; set 1 to disabled slave mode
    iic_base->IC_CON &= 0xEF;
	iic_base->IC_CON |= val;

    if (iic_status == DW_IIC_EN) {
        dw_iic_enable(iic_base);
    }
}
void dw_iic_set_transfer_speed_fast(dw_iic_regs_t *iic_base)
{
    uint32_t speed_config = iic_base->IC_CON;
    speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
    speed_config |= DW_IIC_CON_SPEEDH_EN;
    iic_base->IC_CON = speed_config;
}

void dw_iic_set_target_address(dw_iic_regs_t *iic_base, uint32_t address)
{
    uint32_t iic_status;
    iic_status = dw_iic_get_iic_status(iic_base);
    dw_iic_disable(iic_base);
    uint32_t target_address = iic_base->IC_TAR;
    target_address &= (DW_IIC_TAR_MASTER_ADDR_MODE | DW_IIC_TAR_SPECIAL | DW_IIC_TAR_GC_OR_START );
    target_address |= address;
    iic_base->IC_TAR = target_address; /* this register can be written only when the I2C is disabled*/

    if (iic_status == DW_IIC_EN) {
        dw_iic_enable(iic_base);
    }
}


/// @brief SI5324读寄存器
/// @param address 外设地址
/// @param RegAde  读的寄存器地址
/// @return 
uint32_t SI5324_ReadReg(uint32_t address,uint32_t RegAde)
{	uint32_t temp;
	dw_iic_regs_t * piic = (dw_iic_regs_t *)0x04000000;
	dw_iic_set_target_address( piic, address ); 
	dw_iic_clear_all_irq( piic );
	dw_iic_enable( piic );


	piic->IC_DATA_CMD = RegAde;

	 /* restart + read+ stop */
    piic->IC_DATA_CMD = 0x700;
	    /* wait */
    while ( 1 ) {
        if ( piic->IC_RAW_INTR_STAT & DW_IIC_RAW_TX_ABRT ) {
            break;
        }

        if ( piic->IC_TXFLR == 0 ) {
            break;
        }
    }
    
    if ( piic->IC_RAW_INTR_STAT & DW_IIC_RAW_TX_ABRT ) {
        temp = piic->IC_TX_ABRT_SOURCE;
        printf( "tx fail, %08x\n", temp );
        dw_iic_disable( piic );
        return (int)__LINE__;
    }

	  /* wait */
    while ( 1 ) {
        if ( piic->IC_RXFLR == 1 ) {
            break;
        }
    }

	uint32_t data = piic->IC_DATA_CMD;
	printf( "data = %08x\n", data );
	// dw_iic_disable( piic );
	return data;
}
/// @brief SI5324写寄存器
/// @param address 外设地址
/// @param RegAde  写的寄存器地址
/// @param value 写的值
uint32_t SI5324_WriteReg(uint32_t address,uint32_t RegAde,uint8_t value)
{
	dw_iic_regs_t * piic = (dw_iic_regs_t *)0x04000000;
    uint32_t temp;
	dw_iic_set_target_address( piic, address );
    
    /**/
    dw_iic_clear_all_irq( piic );
    dw_iic_enable( piic );
    
    /* write */
    piic->IC_DATA_CMD = RegAde;
	piic->IC_DATA_CMD = (0x2<<8)|value;
    

    /* wait */
    while ( 1 ) {
        if ( piic->IC_RAW_INTR_STAT & DW_IIC_RAW_TX_ABRT ) {
            break;
        }

        if ( piic->IC_TXFLR == 0 ) {
            break;
        }
    }
    
    if ( piic->IC_RAW_INTR_STAT & DW_IIC_RAW_TX_ABRT ) {
        temp = piic->IC_TX_ABRT_SOURCE;
        printf( "tx fail, %08x\n", temp );

        /**/
        dw_iic_disable( piic );
        return (int)__LINE__;
    }

    /* finish, deinit */
    dw_iic_disable( piic );
    return 0;
}

////
int bl2_dbg_iic_test( void * pctx, int argc, const char * argv[] )
{
	dw_iic_regs_t * piic = (dw_iic_regs_t *)0x04000000;
    uint32_t temp;
    
    /**/
    dw_iic_init( piic, 300000 );
    
    /**/
    dw_iic_set_master_mode( piic );
    dw_iic_set_transfer_speed_fast( piic );



	SI5324_ReadReg(0x68,0x75);
	// SI5324_WriteReg(0x68,0x1D,0x11);
	// SI5324_ReadReg(0x68,0x1D);
	
	printf("iic init ok\n");
 	return 0;
}

int bl2_dbg_info( void * pctx, int argc, const char * argv[] )
{
	uint64_t temp;

	temp = csr_read( mapbaddr );

	printf( "mapbaddr = %x, %x\n",  (uint32_t)(temp >> 32),  (uint32_t)temp );
	return 0;
}



int bl2_dbg_timer( void * pctx, int argc, const char * argv[] )
{
	dw_timer_regs_t * ptmr = (dw_timer_regs_t *)CVI_TIMER0_BASE;

	//
	ptmr->TLC = 50000000ul;
	ptmr->TCR = 3;

	//
	csi_vic_set_prio( 79, 3 );
	csi_vic_enable_irq( 79 );
	return 0;
}


/*
关闭 data cache
*/
int bl2_dbg_cache( void * pctx, int argc, const char * argv[] )
{
	uint64_t temp;
	
	/**/
	__DCACHE_CIALL();
	__DSB();

	temp = __get_MHCR();
	__set_MHCR( temp & 0xFFD );
	
	printf( "mhcr org = %x\n", (uint32_t)temp );
	return 0;
}





extern int bl2_dbg_usb_init( void * pctx, int argc, const char * argv[] );



int log_init( int tsiz );
int log_flush( void );


int bl2_dbg_logcat( void * pctx, int argc, const char * argv[] )
{
	log_flush();
	return 0;
}


int bl2_dbg_rtscore( void * pctx, int argc, const char * argv[] )
{
	uint32_t temp;
	uint32_t tsiz;

	// check : 0x0E000040, 0x0E000044, 0x0E00004C .
	temp = read_reg( 0x0E00004C );
	if ( temp != 0x87654321 )  {
		return 123;
	}

	// memcpy
	temp = read_reg( 0x0E000040 );
	tsiz = read_reg( 0x0E000044 );
	memcpy( (void *)(intptr_t)0x3BC00000, (void *)(intptr_t)temp, (size_t)tsiz );

	// SEC_SUBSYS_BASE
	write_reg( 0x020B0004, 0x2000 );
	write_reg( 0x020B0020, 0x3BC00000 );
	write_reg( 0x020B0024, 0 );
	
	/**/
	__DCACHE_CIALL();
	__DSB();

	// 
	temp = read_reg( 0x03003024 );
	temp = temp | 0x40;
	write_reg( 0x03003024, temp );
	return 0;
}



int test_ecall( uint32_t esno, intptr_t arg0, intptr_t arg1, intptr_t arg2 )
{
    register uintptr_t a7 asm("a7") = (uintptr_t)esno;
    register intptr_t a0 asm("a0") = arg0;
    register intptr_t a1 asm("a1") = arg1;
    register intptr_t a2 asm("a2") = arg2;
	    
    asm volatile("ecall"
                : "+r"(a0)
                : "r"(a1), "r"(a2), "r"(a7)
                : "memory");
	return a0;
}


int bl2_dbg_uget( void * pctx, int argc, const char * argv[] )
{
	int iret;
	int tlen;
	void * ptr;

	// __disable_irq();
	iret = upk_recv_from_dev( &ptr, &tlen );
	// __enable_irq();

	if ( iret != 0 )  {
		printf( "get pkt fail, %d\n", iret );
		return 1;
	}

	/* dump */
	csi_dcache_invalid_range( ptr, tlen );
	debug_dump_hex( ptr, tlen );
	return 0;
}


static uint32_t uputsn = 0;

int bl2_dbg_uput( void * pctx, int argc, const char * argv[] )
{
	int iret;
	uint8_t * ptr;
	
	ptr = upk_alloc();
	
	iret = sprintf( (char *)ptr, "bulk in sn=%u\n", uputsn );
	test_ecall( 123, (intptr_t)ptr, iret, 0 );

	/**/
	uputsn += 1;
	return 0;
}



int bl2_dbg_uloop( void * pctx, int argc, const char * argv[] )
{
	int iret;
	int tlen;
	void * ptr;

	while ( true )  {
	
		// __disable_irq();
		iret = upk_recv_from_dev( &ptr, &tlen );
		// __enable_irq();

		if ( iret != 0 )  {
			
			//
			__WFI();
			continue;
		}

		/* dump */
		csi_dcache_invalid_range( ptr, tlen );
		debug_dump_hex( ptr, tlen );

		/* send back to host */
		test_ecall( 123, (intptr_t)ptr, tlen, 0 );
	}

	return 0;
}



#define SDIF_TRANS_INT_DIS			0x100	// 传输中断禁用标志
#define SDIF_TRANS_ERR_CHK_EN		0x080	// 传输错误检查使能标志
#define SDIF_TRANS_MULTI			0x020	// 多块传输标志
#define SDIF_TRANS_READ				0x010	// 读传输标志
#define SDIF_TRANS_BLK_CNT_EN		0x002	// 块计数使能标志
#define SDIF_TRANS_DMA_EN			0x001	// DMA传输使能标志

#define SDIF_CMD_DATA               0x020	// 命令数据标志
#define SDIF_CMD_IDX_CHECK          0x010	// 命令索引检查标志
#define SDIF_CMD_CRC_CHECK          0x008	// 命令CRC检查标志

#define SDIF_CMD_RESP_136          	0x001	// 136位响应标志
#define SDIF_CMD_RESP_48          	0x002	// 48位响应标志
#define SDIF_CMD_RESP_48_BUSY      	0x003	// 48位响应且忙标志

#define SDIF_INT_XFER_COMPLETE		0x001	// 传输完成中断标志
#define SDIF_INT_BUF_RD_READY 		0x020	// 缓冲区读准备中断标志
#define SDIF_INT_ERROR 				0x8000	// 错误中断标志



/*
CMD3 : SEND_RELATIVE_ADDR, R6
*/
int sdcard_test( void * pctx, int argc, const char * argv[] )
{
	cvi_sdhc_regs_t * psdhc = (cvi_sdhc_regs_t *)0x4310000;
	uint32_t temp;
	uint32_t resp;
	uint32_t told;
	uint32_t tick;
	
	/**/
	psdhc->BlkSize = 0;
	psdhc->Argument = 0;
	psdhc->TransMode = 0x33;
	psdhc->Command = (3ul << 8) | SDIF_CMD_IDX_CHECK | SDIF_CMD_CRC_CHECK | SDIF_CMD_RESP_48;
	told = __get_MTIME();

	/* wait .. */
	while ( true )  {

		temp = psdhc->NormalIntStatus;

		if ( temp & SDIF_INT_ERROR )  {
			printf( "error1 : %08x\n", temp );
			temp = psdhc->ErrorIntStatus;
			printf( "error2 : %08x\n", temp );
			return 22;
		}

		if ( temp & SDIF_INT_XFER_COMPLETE )  {
			psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
			break;
		}

		tick = __get_MTIME();
		tick = tick - told;
		if ( tick >= 25000000 ) {
			printf( "timeout..\n" );
			return 44;
		}		
	}

	
	// todo : check response.
	resp = psdhc->Response[0];
	printf( "resp : %08x\n", resp );
	return 0;

}

int bl2_dbg_cycle( void * pctx, int argc, const char * argv[] )
{
	uint64_t temp;
	uint64_t time1;


	temp = __get_MCYCLE();
	
	time1 = __get_MTIME();
	while ( true  )  {
		uint64_t time2;
		time2 = __get_MTIME();
		if ( (time2 - time1) >= 1000 )  {
			time1 = time2 - time1;
			break;
		}
	}

	
	temp = __get_MCYCLE() - temp;
	
	printf( "cycle : %x\n", (uint32_t)temp );
	printf( " time : %x\n", (uint32_t)time1 );

	temp = temp / time1;
	printf( "multi : %x\n", (uint32_t)temp );
	return 0;
}

int b12_dbg_cmd0(void *pctx, int argc, const char *argv[])
{
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

    // Clear error status
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize = 0x200;
    psdhc->Argument = 0;
    psdhc->TransMode = SDIF_TRANS_ERR_CHK_EN | SDIF_TRANS_READ;
    psdhc->Command = (0 << 8) ;

    told = __get_MTIME();

    // Wait for response
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }

        if (temp & SDIF_INT_ERROR) {
            printf("error1 : %08x\n", temp);
            return 22;
        }

        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("error2 : %08x\n", temp);
            return 33;
        }

        tick = __get_MTIME();
        tick = tick - told;
        if (tick >= 25000000) {
            printf("timeout..\n");
            return 44;
        }
    }

    return 0;
}





//cmd17 R1
//对于标准容量SD存储卡，此命令读取SET_BLOCKLEN命令所选大小的块。1对于SDHC、SDXC和SDUC卡，无论SET_BLOCKLEN命令如何，块长度都是固定的512字节。
int b12_dbg_cmd17( void * pctx, int argc, const char * argv[] )
{

	uint8_t tary[512];
	 if (argc < 2) {
        printf("Error: No Argument provided.\n");
        return 1; // 返回一个错误码
    }	
	uint64_t argument = strtoul(argv[1], NULL, 16);
	printf("argument: %x\n",argument);
	sdcard_read_single(argument,tary);
	return 0;
    
}


int cmd3(){
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;


	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize =0;
    psdhc->Argument = 0;
    psdhc->TransMode =  SDIF_TRANS_READ ;

    // Send CMD3 to get RCA
    psdhc->Command = (3 << 8)  | SDIF_CMD_IDX_CHECK | SDIF_CMD_CRC_CHECK | SDIF_CMD_RESP_48;
    told = __get_MTIME();

    // Wait for response
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }

        if (temp & SDIF_INT_ERROR) {
            printf("error1 : %08x\n", temp);
            return 22;
        }

        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("error2 : %08x\n", temp);
            return 33;
        }

        tick = __get_MTIME();
        tick = tick - told;
        if (tick >= 25000000) {
            printf("timeout..\n");
            return 44;
        }
    }

    // Get response
    resp = psdhc->Response[0];
	
    printf("RCA : %08x\n", resp);
    return resp;
}

//cmd3 R6
//命令用于发送CMD3命令，获取卡的RCA
int b12_dbg_sd_cmd3(void *pctx, int argc, const char *argv[])
{
    uint32_t resp;
    cmd3();
    return 0;
}


//cmd2 R2
//命令用于读取卡的CID寄存器
int b12_dbg_cmd2(void *pctx, int argc, const char *argv[]) {
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;


    // Clear error status
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize = 0x200;
    psdhc->Argument = 0;
    psdhc->TransMode =  SDIF_TRANS_READ;
    psdhc->Command = (2 << 8) |SDIF_CMD_DATA| SDIF_CMD_CRC_CHECK|SDIF_CMD_RESP_136;

    told = __get_MTIME();

    // Wait for completion
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }
        if (temp & SDIF_INT_ERROR) {
            printf("CMD2 error1 : %08x\n", temp);
            return 22;
        }
        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("CMD2 error2 : %08x\n", temp);
            return 33;
        }
        tick = __get_MTIME();
        if (tick - told >= 25000000) {
            printf("CMD2 timeout..\n");
            return 44;
        }
    }

    // Read response
    for (int i = 0; i <= 4; i++) {
        resp = psdhc->Response[i];
        printf("resp[%d] : %08x\n", i, resp);
    }

    psdhc->NormalIntStatus = SDIF_INT_BUF_RD_READY;
    return 0;
}


//cmd13 R1
//命令用于读取卡的CID或CSD寄存器
int b12_dbg_cmd13(void *pctx, int argc, const char *argv[])
{
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
	uint32_t status;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

	 if (argc < 2) {
        printf("Error: No RCA provided.\n");
        return 1; // 返回一个错误码
    }

	uint64_t argument = strtoul(argv[1], NULL, 16); // 获取 卡的RCA

    // Clear error status
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize = 0x200;
    psdhc->Argument = argument; // CMD13的参数 卡的RCA
    psdhc->TransMode = SDIF_TRANS_ERR_CHK_EN | SDIF_TRANS_READ;
    psdhc->Command = (13 << 8) |SDIF_CMD_CRC_CHECK|SDIF_CMD_IDX_CHECK|SDIF_CMD_RESP_48;

    told = __get_MTIME();


    // Wait for response
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }

        if (temp & SDIF_INT_ERROR) {
            printf("error1 : %08x\n", temp);
            return 22;
        }

        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("error2 : %08x\n", temp);
            return 33;
        }

        tick = __get_MTIME();
        tick = tick - told;
        if (tick >= 25000000) {
            printf("timeout..\n");
            return 44;
        }
    }

    for (int i = 0; i < 4; i++) {
        resp = psdhc->Response[i];
        printf("resp[%d] : %08x\n", i, resp);
		if (i == 0)
		{
			 status=(resp >> 9) & 0xF; // 提取9到12位的状态值
		}
    }

	switch (status) {
		case 0:
			printf("Card status: idle\n");
			break;
		case 1:
			printf("Card status: ready\n");
			break;
		case 2:
			printf("Card status: ident\n");
			break;
		case 3:
			printf("Card status: stby\n");
			break;
		case 4:
			printf("Card status: tran\n");
			break;
		case 5:
			printf("Card status: data\n");
			break;
		case 6:
			printf("Card status: rcv\n");
			break;
		case 7:
			printf("Card status: prg\n");
			break;
		case 8:
			printf("Card status: dis\n");
			break;
		default:
			printf("Card status: reserved or unknown\n");
			break;
	}

        return 0;
}


int cmd7(uint64_t argument){
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

    // 清除错误状态
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // 设置块大小为0x200
    psdhc->BlkSize = 0;
    psdhc->Argument = argument; // CMD7的参数 卡的RCA
    psdhc->TransMode = 0; // 传输模式
    psdhc->Command = (7 << 8) | SDIF_CMD_DATA|SDIF_CMD_IDX_CHECK | SDIF_CMD_CRC_CHECK | SDIF_CMD_RESP_48_BUSY; 
    told = __get_MTIME();

    // 等待完成
     while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }

        if (temp & SDIF_INT_ERROR) {
            printf("error1 : %08x\n", temp);
            return 22;
        }

        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("error2 : %08x\n", temp);
            return 33;
        }

        tick = __get_MTIME();
        tick = tick - told;
        if (tick >= 25000000) {
            printf("timeout..\n");
            return 44;
        }
    }

    resp = psdhc->Response[0];
	
    // printf("RCA : %08x\n", resp);
     psdhc->NormalIntStatus = SDIF_INT_BUF_RD_READY;
    return 0;


}
//cmd7	R1	
//命令在待机和传输状态之间或编程和断开连接状态之间切换卡。在这两种情况下，卡都是由其自己的相对地址选择的，并由任何其他地址取消选择；
//地址0取消选择所有。如果RCA等于0，则主机可以执行以下操作之一：-使用其他RCA号码执行卡取消选择。-重新发送CMD3以将其RCA号码更改为0以外的号码，然后使用RCA=0的CMD7取消卡选择
int b12_dbg_cmd7(void *pctx, int argc, const char *argv[]) {
    if (argc < 2) {
        printf("Error: No RCA provided.\n");
        return 1; // 返回一个错误码
    }

	uint64_t argument = strtoul(argv[1], NULL, 16); // 获取 卡的RCA
    cmd7(argument);
    return 0;
}

//cmd10 R2 寻址卡在CMD线上发送其卡标识
int b12_dbg_cmd10(void *pctx, int argc, const char *argv[]) {
    uint32_t temp;
    uint32_t resp;
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

	 if (argc < 2) {
        printf("Error: No RCA provided.\n");
        return 1; // 返回一个错误码
    }

	uint64_t argument = strtoul(argv[1], NULL, 16); // 获取 卡的RCA

    // Clear error status
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

	psdhc->NormalIntStatus=0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize = 0;
    psdhc->Argument =  argument;
    psdhc->TransMode = 0x010;
    psdhc->Command = (10 << 8) | SDIF_CMD_DATA|SDIF_CMD_CRC_CHECK|SDIF_CMD_RESP_136;

    told = __get_MTIME();

    // Wait for completion
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }
        if (temp & SDIF_INT_ERROR) {
            printf("CMD10 error1 : %08x\n", temp);
            return 22;
        }
        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("CMD10 error2 : %08x\n", temp);
            return 33;
        }
        tick = __get_MTIME();
        if (tick - told >= 25000000) {
            printf("CMD10 timeout..\n");
            return 44;
        }
    }

    // Read response
    for (int i = 0; i <= 3; i++) {
        resp = psdhc->Response[i];
        printf("resp[%d] : %08x\n", i, resp);
    }


    psdhc->NormalIntStatus = SDIF_INT_BUF_RD_READY;
    return 0;
}

// 提取指定位的函数
uint32_t extract_bits(uint32_t value, int start_bit, int end_bit) {
    uint32_t mask = ((1ULL << (end_bit - start_bit + 1)) - 1) << start_bit;
    return (value & mask) >> start_bit;
}

uint32_t pow(uint32_t base, uint32_t exp) {
    uint32_t result = 1;
    for (uint32_t i = 0; i < exp; i++) {
        result *= base;
    }
	return result;
}


int global_variable = 512;  // 定义全局变量


int cmd9(){
    uint32_t temp;
    uint32_t resp[3]; // 假设响应是128位的，分成4个32位部分
    uint32_t told;
    uint32_t tick;
    cvi_sdhc_regs_t *psdhc = (cvi_sdhc_regs_t *)0x4310000;

    cmd7(0); // 切换状态
    uint64_t RCA= cmd3(); // 获取卡的RCA
    // Clear error status
    temp = psdhc->ErrorIntStatus;
    psdhc->ErrorIntStatus = temp;

    psdhc->NormalIntStatus = 0xFFFF; // 清除中断标志

    // Set block size to 0x200
    psdhc->BlkSize = 0;
    psdhc->Argument = RCA;
    psdhc->TransMode = 0x010;
    psdhc->Command = (9 << 8) | SDIF_CMD_CRC_CHECK | SDIF_CMD_RESP_136;

    told = __get_MTIME();

    // Wait for completion
    while (true) {
        temp = psdhc->NormalIntStatus;
        if (temp & SDIF_INT_XFER_COMPLETE) {
            psdhc->NormalIntStatus = SDIF_INT_XFER_COMPLETE;
            break;
        }
        if (temp & SDIF_INT_ERROR) {
            printf("CMD9 error1 : %08x\n", temp);
            return 22;
        }
        temp = psdhc->ErrorIntStatus;
        if (temp != 0) {
            printf("CMD9 error2 : %08x\n", temp);
            return 33;
        }
        tick = __get_MTIME();
        if (tick - told >= 25000000) {
            printf("CMD9 timeout..\n");
            return 44;
        }
    }

    // Read response
    for (int i = 0; i <= 3; i++) {
        resp[i] = psdhc->Response[i];
        // printf("resp[%d] : %08x\n", i, resp[i]);
    }
	
	resp[3]=resp[3]<<8|resp[2]>>24; 
	resp[2]=resp[2]<<8|resp[1]>>24; 
	resp[1]=resp[1]<<8|resp[0]>>24; 
	resp[0]=resp[0]<<8;

    // 提取C_SIZE、C_SIZE_MULT、READ_BL_LEN指定的三个数据位
    uint32_t C_SIZE = extract_bits(resp[1], 30, 31) | (extract_bits(resp[2], 0, 9) << 2); // 62-73位
    uint32_t C_SIZE_MULT = extract_bits(resp[1],15, 17); // 47-49位
    uint32_t READ_BL_LEN = extract_bits(resp[2], 16, 19); // 80-83位

    // printf("C_SIZE: %u\n", C_SIZE);
    // printf("C_SIZE_MULT: %u\n", C_SIZE_MULT);
    // printf("READ_BL_LEN: %u\n", READ_BL_LEN);

	uint32_t value_MB=C_SIZE*pow(2,(C_SIZE_MULT+2+READ_BL_LEN))/1024/1024;

	if(value_MB == 0)
	{
		printf("Version 2.00 or later\n");
		uint32_t C_SIZE_2=extract_bits(resp[1],16,31)|extract_bits(resp[2],0,5)<<16; // 48-69位
		value_MB=(C_SIZE_2+1)*512/1024;

		printf("value_MB: %uMB\n", value_MB);
		printf("value_GB: %uGB\n", value_MB/1024);
		psdhc->NormalIntStatus = SDIF_INT_BUF_RD_READY;
        global_variable = 1;  
        return 1;
	}
	printf("value_MB: %uMB\n", value_MB);
    psdhc->NormalIntStatus = SDIF_INT_BUF_RD_READY;
    // printf("global_variable=%d\n",global_variable);
    return 2;
}
// cmd9 R2 读取卡的CSD寄存器
// 读取卡内存容量大小
int b12_dbg_cmd9(void *pctx, int argc, const char *argv[]) {

    cmd9();
    return 0;
}

int bl2_dbg_fatfs( void * pctx, int argc, const char * argv[] )
{
	int iret;
	uint32_t temp;
	uint32_t tsiz;
	fatfs_t fsinfo;
	if ( argc < 3 )  {
		goto usage;
	}
	iret = debug_str2uint( argv[2], &temp );
	if ( iret != 0 )  {
		printf( "args fmt err, %d\n", iret );
		goto usage;
	}


	//
	iret = fatfs_init( &fsinfo );
	if ( iret != 0 )  {
		printf( "fatfs info fail, %d\n", iret );
		return 1;
	}

	iret = fatfs_fstat( &fsinfo, argv[1], &tsiz );
	if ( iret != 0 )  {
		printf( "fstat iret = %d\n", iret );
		return 2;
	}
	
	printf( "fstat ok, size=%u\n", tsiz );
	if ( tsiz <= 0 )  {
		return 3;
	}

	iret = fatfs_fread( &fsinfo, argv[1], (uint8_t *)(uintptr_t)temp );
	if ( iret <= 0 )  {
		printf( "fread iret = %d\n", iret );
		return 3;
	}


	printf( "read succ..\n" );
	return 0;

usage:
	printf( "usage:\n" );
	printf( "\t%s <fname> <addr>\n", argv[0] );
	return 0;
}
extern int bl2_dbg_clock( void * pctx, int argc, const char * argv[] );

int text( void * pctx, int argc, const char * argv[] )
{	


    return 0;
}

int sd_clock(void)
{
	clk_div_regs_t * pdiv = (clk_div_regs_t *)CLK_DIV_BASE;
	uint32_t temp;


	pdiv->DIV_SD0 = 0x000F0009; 


	temp = pdiv->CLK_BYP[0];

	pdiv->CLK_BYP[0] =temp & 0xFFFFFFBF;


    printf("sd clock ok\n");
	return 0;

}


int main( void )
{
    int iret; // 定义一个整型变量iret，用于存储函数返回值
    char spad[128]; // 定义一个字符数组spad，用于存储用户输入的命令行

    printf( "hello...\n" ); // 打印欢迎信息
    qspi_pad_config(); // 配置QSPI接口

    sd_clock(); // 配置SD卡时钟
    debug_cli_init(); // 初始化调试命令行接口

    // cmd9(); 

    debug_add_cmd( "spi", bl2_dbg_spi, NULL ); // 添加调试命令"gpio"，对应处理函数bl2_dbg_gpio
    debug_add_cmd( "timer", bl2_dbg_timer, NULL ); // 添加调试命令"timer"，对应处理函数bl2_dbg_timer
    debug_add_cmd( "usbd", bl2_dbg_usb_init, NULL ); // 添加调试命令"usbd"，对应处理函数bl2_dbg_usb_init
    debug_add_cmd( "logcat", bl2_dbg_logcat, NULL ); // 添加调试命令"logcat"，对应处理函数bl2_dbg_logcat
    
    debug_add_cmd( "cache", bl2_dbg_cache, NULL ); // 添加调试命令"cache"，对应处理函数bl2_dbg_cache
    debug_add_cmd( "rtscore", bl2_dbg_rtscore, NULL ); // 添加调试命令"rtscore"，对应处理函数bl2_dbg_rtscore
    
    debug_add_cmd( "uget", bl2_dbg_uget, NULL ); // 添加调试命令"uget"，对应处理函数bl2_dbg_uget
    debug_add_cmd( "uput", bl2_dbg_uput, NULL ); // 添加调试命令"uput"，对应处理函数bl2_dbg_uput
    debug_add_cmd( "uloop", bl2_dbg_uloop, NULL ); // 添加调试命令"uloop"，对应处理函数bl2_dbg_uloop
    
    debug_add_cmd( "sdtest", sdcard_test, NULL ); // 添加调试命令"sdtest"，对应处理函数sdcard_test
    debug_add_cmd( "cycle", bl2_dbg_cycle, NULL ); // 添加调试命令"cycle"，对应处理函数bl2_dbg_cycle
    debug_add_cmd( "clock", bl2_dbg_clock, NULL ); // 添加调试命令"clock"，对应处理函数bl2_dbg_clock

    debug_add_cmd( "nor", bl2_dbg_nor, NULL ); // 添加调试命令"nor"，对应处理函数bl2_dbg_nor
    debug_add_cmd( "norread", bl2_dbg_noread, NULL ); // 添加调试命令"norread"，对应处理函数bl2_dbg_noread
    debug_add_cmd( "norwrite", bl2_dbg_norwrite, NULL ); // 添加调试命令"norwrite"，对应处理函数bl2_dbg_norwrite
    debug_add_cmd( "iic", bl2_dbg_iic_test, NULL); // 添加调试命令"iic"，对应处理函数bl2_dbg_iic_test

	debug_add_cmd("cmd0", b12_dbg_cmd0, NULL); // 添加调试命令"cmd0"，对应处理函数b12_dbg_cmd0
	debug_add_cmd("cmd2", b12_dbg_cmd2, NULL); // 添加调试命令"cmd2"，对应处理函数b12_dbg_cmd2
	debug_add_cmd("cmd3", b12_dbg_sd_cmd3, NULL); // 添加调试命令"cmd3"，对应处理函数b12_dbg_sd_cmd3
	debug_add_cmd("cmd7", b12_dbg_cmd7, NULL); // 添加调试命令"cmd7"，对应处理函数b12_dbg_cmd7
	debug_add_cmd("cmd9", b12_dbg_cmd9, NULL); // 添加调试命令"cmd9"，对应处理函数b12_dbg_cmd9
	debug_add_cmd("cmd10", b12_dbg_cmd10, NULL); // 添加调试命令"cmd10"，对应处理函数b12_dbg_cmd10
	debug_add_cmd("cmd13", b12_dbg_cmd13, NULL); // 添加调试命令"cmd13"，对应处理函数b12_dbg_cmd13
	debug_add_cmd("cmd17", b12_dbg_cmd17, NULL); // 添加调试命令"cmd17"，对应处理函数b12_dbg_cmd17

	
	debug_add_cmd( "fatfs", bl2_dbg_fatfs, NULL );

	debug_add_cmd("text",text,NULL); // 添加调试命令"text"，对应处理函数text

    // 
    log_init( 16000 ); // 初始化日志系统，设置日志缓冲区大小为16000字节

    /* packet memory pool ...*/
    iret = upk_init(); // 初始化数据包内存池，并将返回值存储在iret中
    printf( "upk pool init = %d\n", iret ); // 打印数据包内存池初始化结果

    // global MIE.
    __enable_irq(); // 使能全局中断

    /**/
    while ( true )  { // 进入无限循环

        /* read line */
        iret = cons_readline( ">> ", 120, spad ); // 从控制台读取一行输入，存储在spad中，并将返回值存储在iret中
        if ( iret != 0 ) { // 如果读取失败
            continue; // 跳过本次循环的剩余部分，继续下一次循环
        }
            
        if ( 0 == strcmp( spad, "quit" ) )  { // 如果输入的命令是"quit"
            break; // 跳出循环，结束程序
        }

        /* proc */
        debug_proc_line( spad ); // 处理输入的命令行
    }

    /**/
    return 0; // 返回0，表示程序正常结束
}





